<?php 
namespace OAuth2\Example\Server\Access;
/**
 * Access handler implementatin
 * @author Wojciech Kupiec <kupiec.w@gmail.com>
 */
class Handler {
    
    protected $_oauth;
    protected $_options;
    
    function __construct(\OAuth2\Server $oauth, $options = array('display_errors' => true))
    {
        $this->setOauth($oauth);
        $this->setOptions($options);
    }
    
  /**
   * Pull out the Authorization HTTP header and return it.
   *
   * Implementing classes may need to override this function for use on
   * non-Apache web servers.
   *
   * @return
   *   The Authorization HTTP header, and FALSE if does not exist.
   *
   * @todo Handle Authorization HTTP header for non-Apache web servers.
   *
   * @ingroup oauth2_section_5
   */
  function getAuthorizationHeader() {
    if (array_key_exists("HTTP_AUTHORIZATION", $_SERVER))
      return $_SERVER["HTTP_AUTHORIZATION"];
    if (function_exists("apache_request_headers")) {
      $headers = apache_request_headers();

      if (array_key_exists("Authorization", $headers))
        return $headers["Authorization"];
    }

    return FALSE;
  }
    /**
   * Pulls the access token out of the HTTP request.
   *
   * Either from the Authorization header or GET/POST/etc.
   *
   * @return
   *   Access token value if present, and FALSE if it isn't.
   *
   * @todo Support PUT or DELETE.
   *
   * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-10#section-5.1
   *
   * @ingroup oauth2_section_5
   */
  protected function getAccessTokenParams(array $get = array(), array $post = array(), $auth_header = null) {
    //$auth_header = $this->getAuthorizationHeader($headers);
    if ($auth_header !== false) {
      // Make sure only the auth header is set
      if (isset($get[OAUTH2_TOKEN_PARAM_NAME]) || isset($post[OAUTH2_TOKEN_PARAM_NAME]))
        throw new \OAuth2\Server\Exception(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST, 'Auth token found in GET or POST when token present in header');

      $auth_header = trim($auth_header);

      // Make sure it's Token authorization
      if (strcmp(substr($auth_header, 0, 5), "OAuth ") !== 0)
        throw new \OAuth2\Server\Exception(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST, 'Auth header found that doesn\'t start with "OAuth"');

      // Parse the rest of the header
      if (preg_match('/\s*OAuth\s*="(.+)"/', substr($auth_header, 5), $matches) == 0 || count($matches) < 2)
        throw new \OAuth2\Server\Exception(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST, 'Malformed auth header');

      return $matches[1];
    }

    if (isset($get[OAUTH2_TOKEN_PARAM_NAME])) {
      if (isset($post[OAUTH2_TOKEN_PARAM_NAME])) // Both GET and POST are not allowed
        throw new \OAuth2\Server\Exception(OAUTH2_HTTP_BAD_REQUEST, OAUTH2_ERROR_INVALID_REQUEST, 'Only send the token in GET or POST, not both');

      return $get[OAUTH2_TOKEN_PARAM_NAME];
    }

    if (isset($post[OAUTH2_TOKEN_PARAM_NAME]))
      return $post[OAUTH2_TOKEN_PARAM_NAME];

    return FALSE;
  }
  
    /**
     * Handles token request
     */
    public function handleAccessRequest() {
        $result = true;
        //echo json_encode($this->getAuthorizationHeader());die;
        $token_param = $this->getAccessTokenParams($_GET, $_POST, $this->getAuthorizationHeader());
        try {
            $result = $this->getOauth()->verifyAccessToken($token_param);
        } catch(\OAuth2\Server\Exception\Authentication $excption) {
            $this->errorWWWAuthenticateResponseHeader($excption->getHttpStatusCode(), $excption->getRealm(), $excption->getError(), $excption->getMessage(), $excption->getErrorUri(), $excption->getScope());
        }
        return $result;
    }
    
    /**
     * Oauth getter
     * @return type 
     */
     public function getOauth()      {
         return $this->_oauth;
     }

     /**
      * Oauth setter
      * 
      * @param type $oauth 
      */
     public function setOauth(\OAuth2\Server $oauth)
     {
         $this->_oauth = $oauth;
     }
     
     /**
      * Options getter
      *
      * @return array
      */
     public function getOptions() 
     {
         return $this->_options;
     }

     /**
      * Options setter
      *
      * @param array $options 
      */
     public function setOptions($options)
     {
         $this->_options = $options;
     }
     
  /**
   * Send a 401 unauthorized header with the given realm and an error, if
   * provided.
   *
   * @param $http_status_code
   *   HTTP status code message as predefined.
   * @param $realm
   *   The "realm" attribute is used to provide the protected resources
   *   partition as defined by [RFC2617].
   * @param $scope
   *   A space-delimited list of scope values indicating the required scope
   *   of the access token for accessing the requested resource.
   * @param $error
   *   The "error" attribute is used to provide the client with the reason
   *   why the access request was declined.
   * @param $error_description
   *   (optional) The "error_description" attribute provides a human-readable text
   *   containing additional information, used to assist in the understanding
   *   and resolution of the error occurred.
   * @param $error_uri
   *   (optional) The "error_uri" attribute provides a URI identifying a human-readable
   *   web page with information about the error, used to offer the end-user
   *   with additional information about the error. If the value is not an
   *   absolute URI, it is relative to the URI of the requested protected
   *   resource.
   *
   * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-10#section-5.2
   *
   * @ingroup oauth2_error
   */
  protected function errorWWWAuthenticateResponseHeader($http_status_code, $realm, $error, $error_description = NULL, $error_uri = NULL, $scope = NULL) {
    $realm = $realm === NULL ? $this->getOauth()->getDefaultAuthenticationRealm() : $realm;
    $displayErrors = isset($options['display_errors']) && $options['display_errors'] === true;
    $result = "WWW-Authenticate: OAuth realm='" . $realm . "'";

    if ($error)
      $result .= ", error='" . $error . "'";

    if ($displayErrors && $error_description)
      $result .= ", error_description='" . $error_description . "'";

    if ($displayErrors && $error_uri)
      $result .= ", error_uri='" . $error_uri . "'";

    if ($scope)
      $result .= ", scope='" . $scope . "'";

    header("HTTP/1.1 ". $http_status_code);
    header($result);

    exit;
  }

}
